package com.leo.chapter05;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 用Future代替直接的结果V，
 *      好处：如果计算结果已经出来，立即返回；如果正在计算结果，那么将阻塞知道结果出来
 *      问题：cache的复合操作不是线程安全的
 * @author xuexiaolei
 * @version 2017年10月14日
 */
public class Memoizer3<A, V> implements Computable<A, V> {
    private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();
    private final Computable<A, V> c;//用来计算的内容，假定会浪费很长时间

    public Memoizer3(Computable<A, V> c) {
        this.c = c;
    }

    @Override public V compute(final A arg) throws InterruptedException {
        Future<V> result = cache.get(arg);
        if (result == null){
            FutureTask<V> ft = new FutureTask<V>(new Callable<V>() {
                @Override public V call() throws Exception {
                    return c.compute(arg);
                }
            });
            result = ft;
            cache.put(arg, result);
            ft.run();
        }
        try {
            return result.get();
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
}
